qinglan.Canvas.Fsm = qinglan.Canvas.Class(function(id, target){
	this.id = id;
	this.target = target;
	
	this.states = {};
	
	this.currentStateId = '-1';
	this.lastStateId = '-1';

	this.suspendStates = [];

	this.onStateChange = qinglan.Function.emptyFun;

	this.isActive = true;

	this.init();
}).methods({
	init: function(){
		qinglan.Array.each(qinglan.Canvas.State.addAdviceList, function(value) {
				var self = this;
				this[value] = function(id, name, fun) {
					return qinglan.Canvas.Fsm._addAdvice.call(self, id, value.toLowerCase().slice(2), name, fun);
				};
			},this);
		// 删除事件
		qinglan.Array.each(qinglan.Canvas.State.removeAdvice, function(value) {
				var self = this;
				this[value] = function(name) {
					return qinglan.Canvas.Fsm._removeAdvice.call(self, id, value.toLowerCase().slice(2), name);
				};
			}, this);
	},
	addStates: function(states){
		qinglan.Type.isArray(states) ? qinglan.Array.each(states,function(state){
			this.states[state.id] = state;
		},this) : (this.states[states.id] = states);
	},
	enter: function(stateid, msg, isSuspended){
		this.setState(stateid, msg, isSuspended);
	},
	leave: function(){
		this.setState(qinglan.Canvas.Fsm.noneState);
	},
	message: function(msg){
		this.states[this.currentStateId].message(msg);
	},
	suspendMsg: function(msg){
		qinglan.Object.each(this.suspendStates, function(state){
			state.message(msg);
		},this);
	},
	setState: function(stateid, msg, isSuspended){
		if(!this.isActive){ return false;}
		if(isSuspended){
			var current = this.states[this.currentStateId];
			current.suspend();
			current.isSuspended = true;
			this.suspendStates.push(current);
		}else{
			this.currentStateId != qinglan.Canvas.Fsm.noneState && this.states[this.currentStateId].leave();
			if(!this.states[stateid].isSuspend()){
				while(this.suspendStates.length > 0){
					var state = this.suspendStates.pop();
					state.leave();
					state.isSuspended = false;
				}
			}
		}

		qinglan.Type.isFunction(this.onStateChange) && this.onStateChange(this.currentStateId, stateid, msg);

		this.lastStateId = this.currentStateId;
		this.currentStateId = stateid;

		if(this.currentStateId != qinglan.Canvas.Fsm.noneState){
			var current = this.states[this.currentStateId];
			if(current.isSuspended){
				current.resume(msg,this.lastStateId);
				current.isSuspended = false;
			}else{
				current.enter(msg,this.lastStateId);
			}
		}
	},
	getCurrentState: function(){
		return this.states[this.currentStateId];
	},
	getState: function(id){
		return this.states[id] || null;
	},
	addAdvice: function(id, type, name, fun){
		var state = this.getState(id);
		!qinglan.Type.isNull(state) && state.addAdvice(type, name, fun);
	},
	removeAdvice: function(id, type, name){
		var state = this.getState(id);
		!qinglan.Type.isNull(state) && state.removeAdvice(type, name, fun);
	}
}).statics({
	noneState: '-1',
	_addAdvice: function(id, type, name, fun){
		(this instanceof qinglan.Canvas.Fsm) && (this.addAdvice(id, type, name, fun));
	},
	_removeAdvice: function(id, type, name){
		(this instanceof qinglan.Canvas.Fsm) && (this.removeAdvice(id, type, name));
	}
});
